package com.huiminpay.transaction.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huiminpay.common.cache.Cache;
import com.huiminpay.common.cache.domain.BusinessException;
import com.huiminpay.common.cache.domain.CommonErrorCode;
import com.huiminpay.transaction.api.dto.PayChannelDTO;
import com.huiminpay.transaction.api.dto.PayChannelParamDTO;
import com.huiminpay.transaction.api.dto.PlatformChannelDTO;
import com.huiminpay.transaction.convert.PayChannelParamConvert;
import com.huiminpay.transaction.convert.PlatformChannelConvert;
import com.huiminpay.transaction.entity.AppPlatformChannel;
import com.huiminpay.transaction.entity.PayChannelParam;
import com.huiminpay.transaction.entity.PlatformChannel;
import com.huiminpay.transaction.mapper.AppPlatformChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelMapper;
import com.huiminpay.transaction.mapper.PayChannelParamMapper;
import com.huiminpay.transaction.mapper.PlatformChannelMapper;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

@Service
public class PayChannelServiceImpl implements IPayChannelService {
    @Autowired
    PlatformChannelMapper platformChannelMapper;
    @Autowired
    AppPlatformChannelMapper appPlatformChannelMapper;
    @Autowired
    PayChannelMapper payChannelMapper;
    @Autowired
    PayChannelParamMapper payChannelParamMapper;
    @Autowired
    Cache cache;

    private String redisPre = "HUIMIN:PAY:";

    @Override
    public List<PlatformChannelDTO> queryPlatformChannel() {
        List<PlatformChannel> platformChannels = platformChannelMapper.selectList(null);

        return PlatformChannelConvert.INSTANCE.listentity2listdto(platformChannels);
    }

    @Override
    public void bindPlatformChannelForApp(String appId, String platformChannelCodes) throws BusinessException {
        // 重复判断  一个应用只开启服务类型只能存在一条数据
        Integer integer = getPlatformCnt(appId, platformChannelCodes);
        if(integer>0){
            throw new BusinessException(CommonErrorCode.E_200240);
        }

        // 保存数据库
        AppPlatformChannel appPlatformChannel = new AppPlatformChannel();
        appPlatformChannel.setAppId(appId);
        appPlatformChannel.setPlatformChannel(platformChannelCodes);
        appPlatformChannelMapper.insert(appPlatformChannel);

    }

    private Integer getPlatformCnt(String appId, String platformChannelCodes) {
        QueryWrapper<AppPlatformChannel> qw = new QueryWrapper<>();
        qw.lambda().eq(AppPlatformChannel::getAppId,appId)
        .eq(AppPlatformChannel::getPlatformChannel,platformChannelCodes);
        return appPlatformChannelMapper.selectCount(qw);
    }

    @Override
    public int queryAppBindPlatformChannel(String appId, String platformChannel) throws BusinessException {
        return getPlatformCnt(appId, platformChannel);
    }

    @Override
    public List<PayChannelDTO> queryPayChannelByPlatformChannel(String platformChannelCode) throws BusinessException {


        return payChannelMapper.queryPayChannelByPlatformChannel(platformChannelCode);
    }

    @Override
    public void savePayChannelParam(PayChannelParamDTO payChannelParamDTO) throws BusinessException {
        // 查询唯一索引条件之1 appPlatformChannelId
        AppPlatformChannel appPlatformChannel = getAppPlatformChannel(payChannelParamDTO);
        if(appPlatformChannel==null){
            throw new BusinessException(CommonErrorCode.E_100101);
        }

        Long appPlatformChannelId = appPlatformChannel.getId();

        // 查询是否已存在数据
        String payChannel = payChannelParamDTO.getPayChannel();

        PayChannelParam payChannelParam = getPayChannelParam(appPlatformChannelId, payChannel);

        // 根据查询结果判断
        if(payChannelParam==null){
            // 数据插入
            payChannelParamDTO.setId(null);//防止前端提交主键ID
            payChannelParamDTO.setAppPlatformChannelId(appPlatformChannelId);//不要忘记了。。。
            payChannelParam = PayChannelParamConvert.INSTANCE.dto2entity(payChannelParamDTO);
            payChannelParamMapper.insert(payChannelParam);
        }else {
            // 数据更新

            payChannelParam.setChannelName(payChannelParamDTO.getChannelName());
            payChannelParam.setParam(payChannelParamDTO.getParam());
            payChannelParamMapper.updateById(payChannelParam);
        }
        // 更新缓存
        updateCache(payChannelParamDTO.getAppId(),payChannelParamDTO.getPlatformChannelCode());

    }

    private PayChannelParam getPayChannelParam(Long appPlatformChannelId, String payChannel) {
        QueryWrapper<PayChannelParam> qw = new QueryWrapper<>();
        qw.lambda().eq(PayChannelParam::getPayChannel,payChannel)
        .eq(PayChannelParam::getAppPlatformChannelId,appPlatformChannelId);
        return payChannelParamMapper.selectOne(qw);
    }

    @Override
    public List<PayChannelParamDTO> queryPayChannelParamByAppAndPlatform(String appId, String platformChannel) throws BusinessException {
        // 查询优化
        // key设置  前缀+platformChannel+appId
        String key = redisPre+platformChannel+":"+appId;
        //判断缓存是否存在
        if(cache.exists(key)){
            /**
             * [
             *        {
             * 		"appPlatformChannelId": 1437353430233460700,
             * 		"channelName": "支付宝手机网站",
             * 		"id": 1437696601786179600,
             * 		"merchantId": 1436266024642142200,
             * 		"param": "{\"name\":456}",
             * 		"payChannel": "ALIPAY_WAP"
             *    },
             *    {
             * 		"appPlatformChannelId": 1437353430233460700,
             * 		"channelName": "微信JSAPI",
             * 		"id": 1437707597917511700,
             * 		"merchantId": 1436266024642142200,
             * 		"param": "{}",
             * 		"payChannel": "WX_JSAPI"
             *    }
             * ]
             */
            String s = cache.get(key);//
            List<PayChannelParamDTO> list = JSON.parseArray(s,PayChannelParamDTO.class);
            return list;
        }

        // 获取 appPlatformChannelId
        AppPlatformChannel appPlatformChannel = getAppPlatformChannel(appId, platformChannel);
        Long appPlatformChannelId = appPlatformChannel.getId();

        // 根据 appPlatformChannelId 查询支付渠道参数列表
        QueryWrapper<PayChannelParam> qw = new QueryWrapper<>();
        qw.lambda().eq(PayChannelParam::getAppPlatformChannelId,appPlatformChannelId);
        List<PayChannelParam> payChannelParams = payChannelParamMapper.selectList(qw);


        return PayChannelParamConvert.INSTANCE.listentity2listdto(payChannelParams);
    }

    @Override
    public PayChannelParamDTO queryParamByAppPlatformAndPayChannel(String appId, String platformChannel, String payChannel) throws BusinessException {
        // key设置  前缀+platformChannel+appId
        String key = redisPre+platformChannel+":"+appId;
        //判断缓存是否存在
        if(cache.exists(key)){

            String s = cache.get(key);//
            List<PayChannelParamDTO> list = JSON.parseArray(s,PayChannelParamDTO.class);
            for (PayChannelParamDTO pay:list ) {
                if(pay.getPayChannel().equals(payChannel)){
                    return pay;
                }
            }

        }

        // 获取 appPlatformChannelId
        AppPlatformChannel appPlatformChannel = getAppPlatformChannel(appId, platformChannel);
        Long appPlatformChannelId = appPlatformChannel.getId();

        //根据 appPlatformChannelId和支付渠道编码 查询支付渠道参数
        PayChannelParam payChannelParam = getPayChannelParam(appPlatformChannelId, payChannel);


        return PayChannelParamConvert.INSTANCE.entity2dto(payChannelParam);
    }

    /**
     * 根据应用业务编码和服务类型编码  查询绑定信息
     * @param appId  应用业务编码
     * @param platformChannel 服务类型编码
     * @return
     */
    private AppPlatformChannel getAppPlatformChannel(String appId, String platformChannel) {
        PayChannelParamDTO payChannelParamDTO = new PayChannelParamDTO();
        payChannelParamDTO.setAppId(appId);
        payChannelParamDTO.setPlatformChannelCode(platformChannel);
        AppPlatformChannel appPlatformChannel = getAppPlatformChannel(payChannelParamDTO);
        if (appPlatformChannel == null) {
            throw new BusinessException(CommonErrorCode.E_100101);
        }
        return appPlatformChannel;
    }

    /**
     * 查询绑定应用绑定服务信息
     * @param payChannelParamDTO
     * @return
     */
    private AppPlatformChannel getAppPlatformChannel(PayChannelParamDTO payChannelParamDTO) {
        QueryWrapper<AppPlatformChannel> qw = new QueryWrapper<>();
        qw.lambda().eq(AppPlatformChannel::getAppId,payChannelParamDTO.getAppId())
                .eq(AppPlatformChannel::getPlatformChannel,payChannelParamDTO.getPlatformChannelCode());
        return appPlatformChannelMapper.selectOne(qw);
    }

    /**
     * 保存缓存
     * @param appId
     * @param platformChannel
     */
    private void updateCache(String appId, String platformChannel){
        List<PayChannelParamDTO> payChannelParamDTOS =
                this.queryPayChannelParamByAppAndPlatform(appId, platformChannel);
        // key设置  前缀+platformChannel+appId
        String key = redisPre+platformChannel+":"+appId;
        // 保存支付渠道参数列表到redis
        cache.set(key, JSON.toJSONString(payChannelParamDTOS));
    }
}
